package com.zenithmind.user.pojo.domain;

import com.baomidou.mybatisplus.annotation.TableName;
import com.zenithmind.common.base.BaseEntity;
import com.zenithmind.user.pojo.domain.valueobject.TenantContact;
import com.zenithmind.user.pojo.domain.valueobject.TenantQuota;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import io.swagger.v3.oas.annotations.media.Schema;

import java.time.LocalDateTime;
import java.util.Objects;

/**
 * 租户聚合根
 * 遵循单一职责原则：只负责租户核心信息管理
 * 遵循封装原则：通过值对象封装复杂属性
 *
 * @author ZenithMind
 * @since 2024-06-30
 */
@EqualsAndHashCode(callSuper = true)
@Getter
@NoArgsConstructor
@Schema(name = "租户实体", description = "租户聚合根")
@TableName("tenant")
public class Tenant extends BaseEntity {

    /**
     * 租户类型枚举
     */
    public enum TenantType {
        ENTERPRISE(1, "企业版"),
        PERSONAL(2, "个人版"),
        TRIAL(3, "试用版");

        private final Integer code;
        private final String name;

        TenantType(Integer code, String name) {
            this.code = code;
            this.name = name;
        }

        public Integer getCode() { return code; }
        public String getName() { return name; }

        public static TenantType fromCode(Integer code) {
            for (TenantType type : values()) {
                if (type.code.equals(code)) {
                    return type;
                }
            }
            throw new IllegalArgumentException("未知的租户类型代码: " + code);
        }
    }

    /**
     * 租户状态枚举
     */
    public enum TenantStatus {
        DISABLED(0, "禁用"),
        ENABLED(1, "启用"),
        TRIAL(2, "试用"),
        EXPIRED(3, "过期");

        private final Integer code;
        private final String name;

        TenantStatus(Integer code, String name) {
            this.code = code;
            this.name = name;
        }

        public Integer getCode() { return code; }
        public String getName() { return name; }

        public static TenantStatus fromCode(Integer code) {
            for (TenantStatus status : values()) {
                if (status.code.equals(code)) {
                    return status;
                }
            }
            throw new IllegalArgumentException("未知的租户状态代码: " + code);
        }
    }

    @Schema(description = "租户编码")
    private String tenantCode;

    @Schema(description = "租户名称")
    private String tenantName;

    @Schema(description = "租户类型")
    private Integer tenantType;

    @Schema(description = "租户域名")
    private String domain;

    @Schema(description = "租户Logo")
    private String logo;

    @Schema(description = "联系人姓名")
    private String contactName;

    @Schema(description = "联系人电话")
    private String contactPhone;

    @Schema(description = "联系人邮箱")
    private String contactEmail;

    @Schema(description = "租户地址")
    private String address;

    @Schema(description = "状态")
    private Integer status;

    @Schema(description = "到期时间")
    private LocalDateTime expireTime;

    @Schema(description = "最大用户数")
    private Integer maxUsers;

    @Schema(description = "当前用户数")
    private Integer currentUsers;

    @Schema(description = "存储配额")
    private Long storageQuota;

    @Schema(description = "已用存储")
    private Long storageUsed;

    @Schema(description = "功能特性配置")
    private String features;

    @Schema(description = "租户设置")
    private String settings;

    /**
     * 构造函数 - 创建新租户
     */
    public Tenant(String tenantCode, String tenantName, TenantType tenantType) {
        this.tenantCode = Objects.requireNonNull(tenantCode, "租户编码不能为空");
        this.tenantName = Objects.requireNonNull(tenantName, "租户名称不能为空");
        this.tenantType = Objects.requireNonNull(tenantType, "租户类型不能为空").getCode();
        this.status = TenantStatus.ENABLED.getCode();
        this.currentUsers = 0;
        this.maxUsers = 100; // 默认最大用户数
        this.storageUsed = 0L;
        this.storageQuota = 10L * 1024L * 1024L * 1024L; // 默认10GB

        validateTenantCode(tenantCode);
        validateTenantName(tenantName);
    }

    /**
     * 更新租户基本信息
     */
    public void updateBasicInfo(String tenantName, String domain, String logo) {
        if (tenantName != null) {
            validateTenantName(tenantName);
            this.tenantName = tenantName;
        }
        this.domain = domain;
        this.logo = logo;
    }

    /**
     * 更新联系信息
     */
    public void updateContactInfo(String contactName, String contactPhone, String contactEmail, String address) {
        this.contactName = contactName;
        this.contactPhone = contactPhone;
        this.contactEmail = contactEmail;
        this.address = address;
    }

    /**
     * 设置到期时间
     */
    public void setExpiration(LocalDateTime expireTime) {
        this.expireTime = expireTime;
        // 如果设置了到期时间且已过期，自动更新状态
        if (expireTime != null && expireTime.isBefore(LocalDateTime.now())) {
            this.status = TenantStatus.EXPIRED.getCode();
        }
    }

    /**
     * 启用租户
     */
    public void enable() {
        this.status = TenantStatus.ENABLED.getCode();
    }

    /**
     * 禁用租户
     */
    public void disable() {
        this.status = TenantStatus.DISABLED.getCode();
    }

    /**
     * 设置为试用状态
     */
    public void setTrial() {
        this.status = TenantStatus.TRIAL.getCode();
    }

    /**
     * 增加用户数
     */
    public boolean addUser() {
        if (this.currentUsers >= this.maxUsers) {
            return false;
        }
        this.currentUsers++;
        return true;
    }

    /**
     * 减少用户数
     */
    public boolean removeUser() {
        if (this.currentUsers <= 0) {
            return false;
        }
        this.currentUsers--;
        return true;
    }

    /**
     * 更新存储使用量
     */
    public boolean updateStorageUsed(long deltaSize) {
        long newUsed = this.storageUsed + deltaSize;
        if (newUsed < 0) {
            return false;
        }
        if (this.storageQuota != null && this.storageQuota > 0 && newUsed > this.storageQuota) {
            return false;
        }
        this.storageUsed = newUsed;
        return true;
    }

    /**
     * 设置配额
     */
    public void setQuota(int maxUsers, long storageQuota) {
        if (maxUsers < this.currentUsers) {
            throw new IllegalArgumentException("最大用户数不能小于当前用户数");
        }
        if (storageQuota > 0 && this.storageUsed > storageQuota) {
            throw new IllegalArgumentException("存储配额不能小于当前使用量");
        }
        this.maxUsers = maxUsers;
        this.storageQuota = storageQuota;
    }

    /**
     * 检查租户是否启用
     */
    public boolean isEnabled() {
        return TenantStatus.ENABLED.getCode().equals(this.status);
    }

    /**
     * 检查租户是否过期
     */
    public boolean isExpired() {
        return TenantStatus.EXPIRED.getCode().equals(this.status) ||
               (this.expireTime != null && this.expireTime.isBefore(LocalDateTime.now()));
    }

    /**
     * 检查是否为试用租户
     */
    public boolean isTrial() {
        return TenantStatus.TRIAL.getCode().equals(this.status);
    }

    /**
     * 检查是否可以添加用户
     */
    public boolean canAddUser() {
        return this.currentUsers < this.maxUsers;
    }

    /**
     * 检查是否可以使用指定大小的存储空间
     */
    public boolean canUseStorage(long size) {
        if (this.storageQuota == null || this.storageQuota <= 0) {
            return true;
        }
        return this.storageUsed + size <= this.storageQuota;
    }

    /**
     * 获取租户类型
     */
    public TenantType getTenantTypeEnum() {
        return TenantType.fromCode(this.tenantType);
    }

    /**
     * 获取租户状态
     */
    public TenantStatus getTenantStatusEnum() {
        return TenantStatus.fromCode(this.status);
    }

    /**
     * 验证租户编码
     */
    private void validateTenantCode(String tenantCode) {
        if (tenantCode == null || tenantCode.trim().isEmpty()) {
            throw new IllegalArgumentException("租户编码不能为空");
        }
        if (tenantCode.length() > 50) {
            throw new IllegalArgumentException("租户编码长度不能超过50个字符");
        }
        if (!tenantCode.matches("^[a-zA-Z0-9_-]+$")) {
            throw new IllegalArgumentException("租户编码只能包含字母、数字、下划线和连字符");
        }
    }

    /**
     * 验证租户名称
     */
    private void validateTenantName(String tenantName) {
        if (tenantName == null || tenantName.trim().isEmpty()) {
            throw new IllegalArgumentException("租户名称不能为空");
        }
        if (tenantName.length() > 100) {
            throw new IllegalArgumentException("租户名称长度不能超过100个字符");
        }
    }

    // MyBatis-Plus需要的setter方法（仅用于数据库映射）
    public void setTenantCode(String tenantCode) { this.tenantCode = tenantCode; }
    public void setTenantName(String tenantName) { this.tenantName = tenantName; }
    public void setTenantType(Integer tenantType) { this.tenantType = tenantType; }
    public void setDomain(String domain) { this.domain = domain; }
    public void setLogo(String logo) { this.logo = logo; }
    public void setContactName(String contactName) { this.contactName = contactName; }
    public void setContactPhone(String contactPhone) { this.contactPhone = contactPhone; }
    public void setContactEmail(String contactEmail) { this.contactEmail = contactEmail; }
    public void setAddress(String address) { this.address = address; }
    public void setStatus(Integer status) { this.status = status; }
    public void setExpireTime(LocalDateTime expireTime) { this.expireTime = expireTime; }
    public void setMaxUsers(Integer maxUsers) { this.maxUsers = maxUsers; }
    public void setCurrentUsers(Integer currentUsers) { this.currentUsers = currentUsers; }
    public void setStorageQuota(Long storageQuota) { this.storageQuota = storageQuota; }
    public void setStorageUsed(Long storageUsed) { this.storageUsed = storageUsed; }
    public void setFeatures(String features) { this.features = features; }
    public void setSettings(String settings) { this.settings = settings; }
}
